package java.redis.impl;

import com.redis.distribute.lock.demo.redis.RedisLock;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/** 不可重入的分布式锁的归一化处理，保证只有当前线程可以解锁当前线程加的锁
 * 解铃还须系铃人，解锁还得加锁的线程
 * 原理：通过threadLocal来确定是否是同一线程解锁
 *
 * @author : owoYam
 * @date : 2020/12/22 15:07
 */
public class RedisLockImplSingleThread implements RedisLock {

    @Resource
    private RedisTemplate redisTemplate;
    private static ThreadLocal<String> localUid = new ThreadLocal<String>();

    @Override
    public boolean tryLock(String key, long timeout, TimeUnit unit) {
        String uuid = UUID.randomUUID().toString();
        //将uuid储存为线程本地变量
        localUid.set(uuid);
        return redisTemplate.opsForValue().setIfAbsent(key,uuid,timeout,unit);
    }

    @Override
    public void releaseLock(String key) {
        if(localUid.get() != null){
            if(localUid.get().equalsIgnoreCase(String.valueOf(redisTemplate.opsForValue().get(key)))){
                //如果已经是本线程，并且已经上锁，则释放锁
                redisTemplate.delete(key);
                localUid.remove();
            }
        }
    }
}
